#include <fontconfig/fontconfig.h>
#include <cairo.h>
#include <glib.h>
#include <stdlib.h>

#define FORMAT_FULLNAME "%{fullname}"

#define THUMB_SIZE 128
#define PADDING_VERTICAL 2
#define PADDING_HORIZONTAL 4

#define DEFAULT_THUMB_STR "Aa"

static gchar* query_font_name(gchar* file);
static gdouble get_thumb_scale(gint width, gint height, gint thumb_size);

static gchar*
query_font_name(gchar* file)
{
    int count;
    FcPattern* pat = FcFreeTypeQuery((FcChar8*)file, 0, NULL, &count);
    if (!pat) {
	return NULL;
    }

    FcChar8* fullname = FcPatternFormat(pat, (FcChar8*)FORMAT_FULLNAME);
    FcPatternDestroy(pat);

    gchar** list = g_strsplit((gchar*)fullname, ",", -1);
    FcStrFree(fullname);

    gchar* name = g_strdup(list[0]);
    g_strfreev(list);

    return name;
}

static gdouble
get_thumb_scale (gint width, gint height, gint thumb_size)
{
    gdouble scale, scale_x, scale_y;
    if (width > (thumb_size - 2 * PADDING_HORIZONTAL)) {
	scale_x = (gdouble)(thumb_size - 2 * PADDING_HORIZONTAL) / width;
    } else {
	scale_x = 1.0;
    }

    if (height > (thumb_size - 2 * PADDING_VERTICAL)) {
	scale_y = (gdouble)(thumb_size - 2 * PADDING_VERTICAL) / height;
    } else {
	scale_y = 1.0;
    }

    scale = MIN(scale_x, scale_y);
    return scale;
}

int
gen_thumbnail(char* file, char* dest, int size)
{
    char* font_name = query_font_name(file);
    if (!font_name) {
	g_printerr("Query font name failed\n");
	return -1;
    }
    
    gint thumb_size = size;
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
							  thumb_size,
							  thumb_size);
    if (!surface) {
	g_printerr("Create surface failed\n");
	return -1;
    }

    cairo_t* cr = cairo_create(surface);
    cairo_select_font_face(cr, font_name,
			   CAIRO_FONT_SLANT_NORMAL,
			   CAIRO_FONT_WEIGHT_BOLD);
    g_free(font_name);

    gint font_size = thumb_size - 2 * PADDING_VERTICAL;
    cairo_set_font_size(cr, font_size);

    cairo_text_extents_t extents;
    cairo_text_extents(cr, DEFAULT_THUMB_STR, &extents);
    gdouble scale = get_thumb_scale(extents.width, extents.height, thumb_size);
    cairo_scale(cr, scale, scale);
    cairo_translate(cr,
		    PADDING_HORIZONTAL - extents.x_bearing + (thumb_size - scale * extents.width) / 2.0,
		    PADDING_VERTICAL - extents.y_bearing + (thumb_size - scale * extents.height) / 2.0);

    // black
    cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
    cairo_show_text(cr, DEFAULT_THUMB_STR);
    cairo_destroy(cr);

    cairo_surface_write_to_png(surface, dest);
    cairo_surface_destroy(surface);

    return 0;
}

int
main(int argc, char* argv[])
{
    if (argc != 4) {
	g_print("Usage: %s <font file> <size> <dest>\n", argv[0]);
	return -1;
    }
    return gen_thumbnail(argv[1], argv[3], atoi(argv[2]));
}
